package com.jindy.module.statement.service.impl;

import com.alibaba.fastjson2.JSON;
import com.jindy.common.constant.Constants;
import com.jindy.common.constant.HttpStatus;
import com.jindy.common.core.domain.AjaxResult;
import com.jindy.common.core.domain.entity.SysDept;
import com.jindy.common.core.domain.entity.SysRole;
import com.jindy.common.core.domain.entity.SysUser;
import com.jindy.common.core.domain.model.LoginUser;
import com.jindy.common.exception.base.BaseException;
import com.jindy.common.utils.DateUtils;
import com.jindy.common.utils.SecurityUtils;
import com.jindy.jpush.utils.JPushUtils;
import com.jindy.jpush.utils.UniJpushUtils;
import com.jindy.module.approvalConfig.domain.ApprovalConfig;
import com.jindy.module.approvalConfig.mapper.ApprovalConfigMapper;
import com.jindy.module.approvalRecord.domain.ApprovalRecord;
import com.jindy.module.approvalRecord.mapper.ApprovalRecordMapper;
import com.jindy.module.constant.StatusConstants;
import com.jindy.module.copy.domain.Copy;
import com.jindy.module.copy.mapper.CopyMapper;
import com.jindy.module.jpush.mapper.JpushMapper;
import com.jindy.module.logisticscost.domain.LogisticsCost;
import com.jindy.module.logisticscost.mapper.LogisticsCostMapper;
import com.jindy.module.machine.domain.MachineRecord;
import com.jindy.module.machine.mapper.MachineRecordMapper;
import com.jindy.module.order.domain.Order;
import com.jindy.module.order.domain.OrderProduct;
import com.jindy.module.order.mapper.OrderMapper;
import com.jindy.module.order.mapper.OrderProductMapper;
import com.jindy.module.outboundorder.mapper.OutboundOrderMachineMapper;
import com.jindy.module.projectEngineerCost.domain.ProjectEngineerCost;
import com.jindy.module.projectEngineerCost.mapper.ProjectEngineerCostMapper;
import com.jindy.module.statement.domain.*;
import com.jindy.module.statement.mapper.*;
import com.jindy.module.statement.service.IAccountStatementService;
import com.jindy.module.statementorder.domain.StatementOrder;
import com.jindy.module.statementorder.mapper.StatementOrderMapper;
import com.jindy.system.service.ISysUserService;
import com.jindy.ws.po.Message;
import com.jindy.ws.service.WebSocketServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static com.jindy.common.constant.Constants.KE_FU_DEPT_ID;
import static com.jindy.common.constant.Constants.WU_LIU_DEPT_ID;


/**
 * 对账单Service业务层处理
 *
 * @author ruoyi
 * @date 2022-10-27
 */
@Service
public class AccountStatementServiceImpl implements IAccountStatementService
{
    private static final Logger LOGGER = LoggerFactory.getLogger(AccountStatementServiceImpl.class);
    @Resource
    private AccountStatementMapper accountStatementMapper;
    @Resource
    private ISysUserService sysUserService;
    @Resource
    private DeductibleExpensesMapper deductibleExpensesMapper;
    @Resource
    private LogisticsExpensesMapper logisticsExpensesMapper;
    @Resource
    private MaintenanceCostMapper maintenanceCostMapper;
    @Resource
    private OtherExpensesMapper otherExpensesMapper;
    @Resource
    private OrderProductMapper orderProductMapper;
    @Resource
    private MachineRecordMapper machineRecordMapper;
    @Resource
    private OutboundOrderMachineMapper outboundOrderMachineMapper;

    @Resource
    private LogisticsCostMapper logisticsCostMapper;

    @Resource
    private OrderMapper orderMapper;
    @Resource
    private StatementExpensesMapper statementExpensesMapper;

    @Resource
    private StatementOrderMapper statementOrderMapper;

    /**
     * 审批记录
     */
    @Resource
    private ApprovalRecordMapper approvalRecordMapper;

    /**
     * 查询人员信息
     */
    @Resource
    private ISysUserService userService;

    /**
     * 审批配置表
     */
    @Resource
    private ApprovalConfigMapper approvalConfigMapper;

    /**
     * 抄送记录
     */
    @Resource
    private CopyMapper copyMapper;

    /**
     * 第三方应用消息推送
     */
    @Autowired
    private JPushUtils jPushUtils;
    /**
     * 内部消息推送
     */
    @Autowired
    private WebSocketServer webSocketServer;

    /**
     * 消息推送设备信息表
     */
    @Resource
    private JpushMapper jpushMapper;

    /**
     * 项目应扣工程费用明细
     */
    @Resource
    private ProjectEngineerCostMapper projectEngineerCostMapper;


    /**
     * 查询对账单
     *
     * @param id 对账单主键
     * @return 对账单
     */
    @Override
    public AccountStatement selectAccountStatementById(Long id)
    {
        AccountStatement or = accountStatementMapper.selectAccountStatementById(id);
        setList(or);
        return or;
    }

    /**
     * 查询对账单列表
     *
     * @param accountStatement 对账单
     * @return 对账单
     */
    @Override
    public List<AccountStatement> selectAccountStatementList(AccountStatement accountStatement)
    {
        List<AccountStatement> list =  accountStatementMapper.selectAccountStatementList(accountStatement);
        if(!CollectionUtils.isEmpty(list)){
            list.forEach(or->{
                setList(or);
            });
        }
        return list;
    }

    /**
     * 查询对账单列表（含业务数据）
     * @param accountStatement
     * @return
     */
    @Override
    public List<AccountStatementApprove> selectAccountStatementApproveList(AccountStatement accountStatement) {
        List<AccountStatementApprove> list =  accountStatementMapper.selectAccountStatementApproveList(accountStatement);
        if(!CollectionUtils.isEmpty(list)){
            list.forEach(or->{
                setApproveList(or);
            });
        }
        return list;
    }

    /**
     * 设置各个明细含业务数据）
     * @param or
     */
    void setApproveList(AccountStatementApprove or){
        //项目应扣费用对象
        DeductibleExpenses deductibleExpenses = new DeductibleExpenses();
        deductibleExpenses.setOrderId(or.getId());
        deductibleExpenses.setOrderType("1");
        List<DeductibleExpenses> deductibleExpensesList = deductibleExpensesMapper.selectDeductibleExpensesList(deductibleExpenses);
        or.setDeductibleExpensesList(deductibleExpensesList);
        //物流及辅料费用对象
        LogisticsExpenses logisticsExpenses = new LogisticsExpenses();
        logisticsExpenses.setOrderId(or.getId());
        logisticsExpenses.setOrderType("1");
        List<LogisticsExpenses> logisticsExpensesList = logisticsExpensesMapper.selectLogisticsExpensesList(logisticsExpenses);
        or.setLogisticsExpensesList(logisticsExpensesList);

        MaintenanceCost maintenanceCost = new MaintenanceCost();
        maintenanceCost.setOrderId(or.getId());
        maintenanceCost.setOrderType("1");
        List<MaintenanceCost> maintenanceCostList = maintenanceCostMapper.selectMaintenanceCostList(maintenanceCost);
        or.setMaintenanceCostList(maintenanceCostList);

        OtherExpenses otherExpenses = new OtherExpenses();
        otherExpenses.setOrderId(or.getId());
        otherExpenses.setOrderType("1");
        List<OtherExpenses> otherExpensesList = otherExpensesMapper.selectOtherExpensesList(otherExpenses);
        or.setOtherExpensesList(otherExpensesList);

        //结算机器费用
        StatementExpenses statementExpenses = new StatementExpenses();
        statementExpenses.setOrderId(or.getOrderId());
        statementExpenses.setAccountStatementId(or.getId());
        statementExpenses.setOrderType("1");
        List<StatementExpenses> statementExpensesList = statementExpensesMapper.selectStatementExpensesList(statementExpenses);
        or.setStatementExpensesList(statementExpensesList);

        //机器明细+使用记录
        //List<Map<String,Object>> mlistall= new ArrayList<>();
        //or.setMachineList(selectMachineList(or));

        //对账单关联订单对象
        StatementOrder statementOrder = new StatementOrder();
        statementOrder.setAccountStatementId(or.getId());
        List<StatementOrder> statementOrderList = statementOrderMapper.selectStatementOrderList(statementOrder);
        or.setStatementOrderList(statementOrderList);

        //对账单关联订单对象
        ProjectEngineerCost projectEngineerCost = new ProjectEngineerCost();
        projectEngineerCost.setOrderId(or.getId());
        List<ProjectEngineerCost> projectEngineerCosts = projectEngineerCostMapper.selectProjectEngineerCostList(projectEngineerCost);
        or.setProjectEngineerCostList(projectEngineerCosts);
    }

    /**
     * 设置各个明细
     * @param or
     */
    void setList(AccountStatement or){
        //项目应扣费用对象
        DeductibleExpenses deductibleExpenses = new DeductibleExpenses();
        deductibleExpenses.setOrderId(or.getId());
        deductibleExpenses.setOrderType("1");
        List<DeductibleExpenses> deductibleExpensesList = deductibleExpensesMapper.selectDeductibleExpensesList(deductibleExpenses);
        or.setDeductibleExpensesList(deductibleExpensesList);
        //物流及辅料费用对象
        LogisticsExpenses logisticsExpenses = new LogisticsExpenses();
        logisticsExpenses.setOrderId(or.getId());
        logisticsExpenses.setOrderType("1");
        List<LogisticsExpenses> logisticsExpensesList = logisticsExpensesMapper.selectLogisticsExpensesList(logisticsExpenses);
        or.setLogisticsExpensesList(logisticsExpensesList);

        MaintenanceCost maintenanceCost = new MaintenanceCost();
        maintenanceCost.setOrderId(or.getId());
        maintenanceCost.setOrderType("1");
        List<MaintenanceCost> maintenanceCostList = maintenanceCostMapper.selectMaintenanceCostList(maintenanceCost);
        or.setMaintenanceCostList(maintenanceCostList);

        OtherExpenses otherExpenses = new OtherExpenses();
        otherExpenses.setOrderId(or.getId());
        otherExpenses.setOrderType("1");
        List<OtherExpenses> otherExpensesList = otherExpensesMapper.selectOtherExpensesList(otherExpenses);
        or.setOtherExpensesList(otherExpensesList);

        //结算机器费用
        StatementExpenses statementExpenses = new StatementExpenses();
        statementExpenses.setOrderId(or.getOrderId());
        statementExpenses.setAccountStatementId(or.getId());
        statementExpenses.setOrderType("1");
        List<StatementExpenses> statementExpensesList = statementExpensesMapper.selectStatementExpensesList(statementExpenses);
        or.setStatementExpensesList(statementExpensesList);

        //机器明细+使用记录
        //List<Map<String,Object>> mlistall= new ArrayList<>();
        //or.setMachineList(selectMachineList(or));

        //对账单关联订单对象
        StatementOrder statementOrder = new StatementOrder();
        statementOrder.setAccountStatementId(or.getId());
        List<StatementOrder> statementOrderList = statementOrderMapper.selectStatementOrderList(statementOrder);
        or.setStatementOrderList(statementOrderList);
    }


    /**
     * date2比date1多的天数
     *
     * @param date1
     * @param date2
     * @return
     */
    private int differentDays(Date date1, Date date2) {
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(date1);

        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(date2);
        int day1 = cal1.get(Calendar.DAY_OF_YEAR);
        int day2 = cal2.get(Calendar.DAY_OF_YEAR);

        int year1 = cal1.get(Calendar.YEAR);
        int year2 = cal2.get(Calendar.YEAR);
        if (year1 != year2)   //同一年
        {
            int timeDistance = 0;
            for (int i = year1; i < year2; i++) {
                if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0)    //闰年
                {
                    timeDistance += 366;
                } else    //不是闰年
                {
                    timeDistance += 365;
                }
            }
            return timeDistance + (day2 - day1);
        } else    //不同年
        {
            return day2 - day1;
        }
    }

    /**
     * 新增对账单
     *
     * @param accountStatement 对账单
     * @return 结果
     */
    @Override
    public AjaxResult insertAccountStatement(AccountStatement accountStatement)
    {
        // 获取当前人
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (loginUser == null) {
            return new AjaxResult(HttpStatus.UNAUTHORIZED,"请先登录");
        }
        // 判断是否再提交
        if (null == accountStatement.getId()){
            //    新增
            addAccountStatement(accountStatement);
        }else{
        //    再提交
            updateAccountStatement(accountStatement);
            //删除审批记录
            approvalRecordMapper.deleteApprovalRecordBySerialNum(accountStatement.getNumber());
            // 删除抄送
            copyMapper.deleteCopyMapperBySerialNum(accountStatement.getNumber());
        }
        // 添加审批记录
        List<Long> addJpushList = addApprovalRecord(accountStatement, loginUser);
        // 新增抄送记录
        List<Long> jpushCopyList = addCopyRecord(accountStatement, loginUser);
        //消息推送
        sendApproveMessage(addJpushList);
        sendCopyMessage(jpushCopyList);
        // 内部消息推送
        sendMessage(addJpushList.get(0),accountStatement);
        return AjaxResult.success();
    }
    /**
     * 给抄送人推送消息
     * @param jpushCopyList
     */
    private void sendCopyMessage(List<Long> jpushCopyList) {
        try {
            List<String> copyRegIds = jpushMapper.selectRegistrationIdsByUserIds(jpushCopyList);
            if (!CollectionUtils.isEmpty(copyRegIds)){
                UniJpushUtils.sendCopyMessage(copyRegIds);
            }
        } catch (Exception e) {
            LOGGER.error("租赁订单抄送人推送通知失败",e);
        }
    }


    /**
     * 给审批人推送消息
     * @param addJpushList
     */
    private void sendApproveMessage(List<Long> addJpushList) {
        try {
            List<String> addRegIds = jpushMapper.selectRegistrationIdsByUserIds(addJpushList);
            if (!CollectionUtils.isEmpty(addRegIds)){
                UniJpushUtils.sendApproveMessage(addRegIds);
            }
        } catch (Exception e) {
            LOGGER.error("租赁订单审批人推送通知失败",e);
        }
    }

    /**
     * 推送消息到前端
     * @param userId
     * @param accountStatement
     */
    private void sendMessage(Long userId, AccountStatement accountStatement) {
        try {
            //发送消息
            Message message = new Message();
            message.setFromId(accountStatement.getSponsor());
            message.setFromName(accountStatement.getSponsorName());
            message.setNextNodeId(userId);
            message.setSerialNum(accountStatement.getOrderNo());
            webSocketServer.onMessage(JSON.toJSONString(message));
        } catch (Exception e) {
            LOGGER.error("结账单内部消息推送失败",e);
        }
    }

    /**
     * 获取抄送记录对象
     *
     * @param accountStatement
     * @param loginUser
     */
    private Copy getCopyRecord(AccountStatement accountStatement, LoginUser loginUser) {
        Copy copyRecord = new Copy();
        copyRecord.setSerialNum(accountStatement.getNumber());
        copyRecord.setUserId(accountStatement.getSponsor());
        copyRecord.setCopyerStatus("0");
        copyRecord.setOrderId(accountStatement.getId());
        copyRecord.setProjectName(accountStatement.getProjectName());
        copyRecord.setUsername(accountStatement.getSponsorName());
        copyRecord.setUpdateTime(DateUtils.parseDate(DateUtils.getTime()));
        copyRecord.setUpdateBy(loginUser.getUsername());
        copyRecord.setCreateBy(loginUser.getUsername());
        copyRecord.setCreateTime(DateUtils.parseDate(DateUtils.getTime()));
        return copyRecord;
    }

    /**
     * 新增抄送记录
     *
     * @param accountStatement
     * @param loginUser
     */
    private List<Long> addCopyRecord(AccountStatement accountStatement, LoginUser loginUser) {
        //  获取抄送人
        List<ApprovalConfig> approvalConfigList = approvalConfigMapper.selectApprovalConfigList(new ApprovalConfig("DZ_COPYER", "1"));
        LOGGER.info("获取抄送人人数"+approvalConfigList.size());
        if (!CollectionUtils.isEmpty(approvalConfigList)) {
            for (ApprovalConfig approvalConfig : approvalConfigList) {
                Copy copyRecord = getCopyRecord(accountStatement, loginUser);
                copyRecord.setCopyerId(approvalConfig.getUserId());
                copyRecord.setCopyerName(approvalConfig.getUsername());
                copyMapper.insertCopy(copyRecord);
            }
        }
        return approvalConfigList.stream().map(approvalConfig -> approvalConfig.getUserId()).collect(Collectors.toList());
    }

    /**
     * 新增审批记录
     *
     * @param accountStatement
     * @param loginUser
     */
    @Transactional(rollbackFor = Exception.class)
    public List<Long> addApprovalRecord(AccountStatement accountStatement, LoginUser loginUser) {
        try {
            boolean isInternalEmployeeResult = isInternalEmployee(accountStatement);
            if (isInternalEmployeeResult) {
                //  发起人是内部人员
                return insertInternalApprovalRecord(accountStatement, loginUser);
            } else {
                //  发起人是外部人员
                return insertOutsideApprovalRecord(accountStatement, loginUser);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 发起人是外部人员 流程记录
     *
     * @param accountStatement
     * @param loginUser
     */
    @Transactional(rollbackFor = Exception.class)
    public List<Long> insertOutsideApprovalRecord(AccountStatement accountStatement, LoginUser loginUser) {
        int sequence = 1;
        //  发起人
        ApprovalRecord firstApprovalRecord = getApprovalRecord(accountStatement, loginUser);
        firstApprovalRecord.setSequence(sequence);
        firstApprovalRecord.setApprovalStatus(Constants.COMPLETED);
        firstApprovalRecord.setTypeOperation(Constants.AGREE);
        firstApprovalRecord.setBusinessStatus(Constants.APPROVE);
        firstApprovalRecord.setUpdateBy(loginUser.getUsername());
        firstApprovalRecord.setApproverId(accountStatement.getSponsor());
        firstApprovalRecord.setApproverName(accountStatement.getSponsorName());
        firstApprovalRecord.setRole("发起人");
        approvalRecordMapper.insertApprovalRecord(firstApprovalRecord);

        sequence++;
        //客服人员
        List<SysUser> kfList = userService.selectUserByDeptId(KE_FU_DEPT_ID);
        if (CollectionUtils.isEmpty(kfList)){
            throw new BaseException("客服人员信息空");
        }
        for (SysUser sysUser : kfList) {
            ApprovalRecord kfApprovalRecord = getApprovalRecord(accountStatement, loginUser);
            kfApprovalRecord.setSequence(sequence);
            kfApprovalRecord.setApprovalStatus(Constants.APPROVE);
            kfApprovalRecord.setApproverId(sysUser.getUserId());
            kfApprovalRecord.setApproverName(sysUser.getUserName());
            kfApprovalRecord.setRole("客服");
            approvalRecordMapper.insertApprovalRecord(kfApprovalRecord);
        }

        sequence++;
        //物流
        List<SysUser> wlList = userService.selectUserByDeptId(WU_LIU_DEPT_ID);
        if (CollectionUtils.isEmpty(wlList)){
            throw new BaseException("物流人员信息空");
        }
        for (SysUser sysUser : wlList) {
            ApprovalRecord kfApprovalRecord = getApprovalRecord(accountStatement, loginUser);
            kfApprovalRecord.setSequence(sequence);
            kfApprovalRecord.setApprovalStatus(Constants.NOT_APPROVED);
            kfApprovalRecord.setApproverId(sysUser.getUserId());
            kfApprovalRecord.setApproverName(sysUser.getUserName());
            kfApprovalRecord.setRole("物流");
            approvalRecordMapper.insertApprovalRecord(kfApprovalRecord);
        }

        sequence++;
        //  第二审批人：渠道经理
        SysUser sysUser = userService.selectUserById(accountStatement.getSponsor());
        if (sysUser == null) {
            throw new RuntimeException("发起人信息错误");
        }
        SysDept dept = sysUser.getDept();
        if (dept == null) {
            throw new RuntimeException("发起人渠道经理职位信息为空");
        }
        ApprovalRecord approvalRecord = getApprovalRecord(accountStatement,loginUser);
        approvalRecord.setSequence(sequence);
        approvalRecord.setApprovalStatus(Constants.NOT_APPROVED);
        approvalRecord.setApproverId(dept.getLeaderId());
        approvalRecord.setApproverName(dept.getLeader());
        approvalRecord.setRole(dept.getLeader());
        approvalRecordMapper.insertApprovalRecord(approvalRecord);

        sequence++;
        //  第二审批人：默认周总
        List<ApprovalConfig> approvalConfigList = approvalConfigMapper.selectApprovalConfigList(new ApprovalConfig("DZ_NB_LEADER", "1"));
        if (CollectionUtils.isEmpty(approvalConfigList)) {
            throw new RuntimeException("请检查审批配置信息：DZ_NB_LEADER");
        }
        addApprovalConfig(sequence, approvalConfigList,accountStatement, loginUser);

        sequence++;
        //  第三审批人业务管理员：默认陈雅晴
        List<ApprovalConfig> thirdApprovalConfigList = approvalConfigMapper.selectApprovalConfigList(new ApprovalConfig("DZ_YWGL", "1"));
        if (CollectionUtils.isEmpty(thirdApprovalConfigList)) {
            throw new RuntimeException("请检查审批配置信息：DZ_CN");
        }
        addApprovalConfig(sequence, thirdApprovalConfigList,accountStatement, loginUser);

        sequence++;
        //  第四审批人财务经理：张文颖
        List<ApprovalConfig> fourthApprovalConfigList = approvalConfigMapper.selectApprovalConfigList(new ApprovalConfig("DZ_CWJL", "1"));
        if (CollectionUtils.isEmpty(fourthApprovalConfigList)) {
            throw new RuntimeException("请检查审批配置信息：DZ_CN");
        }
        addApprovalConfig(sequence, fourthApprovalConfigList,accountStatement, loginUser);

        if (dept.getLeaderId()==null){
            throw new RuntimeException("渠道经理id为空");
        }
        return kfList.stream().map(SysUser::getUserId).collect(Collectors.toList());
    }

    /**
     * 获取审批记录对象
     *
     * @param accountStatement
     * @param loginUser
     * @return
     */
    private ApprovalRecord getApprovalRecord(AccountStatement accountStatement, LoginUser loginUser) {
        ApprovalRecord approvalRecord = new ApprovalRecord();
        approvalRecord.setSerialNum(accountStatement.getNumber());
        approvalRecord.setProjectName(accountStatement.getProjectName());
        approvalRecord.setOrderId(accountStatement.getId());
        approvalRecord.setUserId(accountStatement.getSponsor());
        approvalRecord.setUserName(accountStatement.getSponsorName());
        approvalRecord.setUpdateTime(DateUtils.parseDate(DateUtils.getTime()));
        approvalRecord.setCreateBy(loginUser.getUsername());
        approvalRecord.setCreateTime(DateUtils.parseDate(DateUtils.getTime()));
        return approvalRecord;
    }

    /**
     * 发起人是内部人员 流程记录
     *
     * @param accountStatement
     * @param loginUser
     */
    @Transactional(rollbackFor = Exception.class)
    public List<Long> insertInternalApprovalRecord(AccountStatement accountStatement, LoginUser loginUser) {
        int sequence = 1;
        //  发起人
        ApprovalRecord firstApprovalRecord = getApprovalRecord(accountStatement, loginUser);
        firstApprovalRecord.setSequence(sequence);
        firstApprovalRecord.setApprovalStatus(Constants.COMPLETED);
        firstApprovalRecord.setTypeOperation(Constants.AGREE);
        firstApprovalRecord.setBusinessStatus(Constants.APPROVE);
        firstApprovalRecord.setUpdateBy(loginUser.getUsername());
        firstApprovalRecord.setApproverId(accountStatement.getSponsor());
        firstApprovalRecord.setApproverName(accountStatement.getSponsorName());
        firstApprovalRecord.setRole("发起人");
        approvalRecordMapper.insertApprovalRecord(firstApprovalRecord);


        sequence++;
        //客服人员
        List<SysUser> kfList = userService.selectUserByDeptId(KE_FU_DEPT_ID);
        if (CollectionUtils.isEmpty(kfList)){
            throw new BaseException("客服人员信息空");
        }
        for (SysUser sysUser : kfList) {
            ApprovalRecord kfApprovalRecord = getApprovalRecord(accountStatement, loginUser);
            kfApprovalRecord.setSequence(sequence);
            kfApprovalRecord.setApprovalStatus(Constants.APPROVE);
            kfApprovalRecord.setApproverId(sysUser.getUserId());
            kfApprovalRecord.setApproverName(sysUser.getUserName());
            kfApprovalRecord.setRole("客服");
            approvalRecordMapper.insertApprovalRecord(kfApprovalRecord);
        }

        sequence++;
        //物流
        List<SysUser> wlList = userService.selectUserByDeptId(WU_LIU_DEPT_ID);
        if (CollectionUtils.isEmpty(wlList)){
            throw new BaseException("物流人员信息空");
        }
        for (SysUser sysUser : wlList) {
            ApprovalRecord kfApprovalRecord = getApprovalRecord(accountStatement, loginUser);
            kfApprovalRecord.setSequence(sequence);
            kfApprovalRecord.setApprovalStatus(Constants.NOT_APPROVED);
            kfApprovalRecord.setApproverId(sysUser.getUserId());
            kfApprovalRecord.setApproverName(sysUser.getUserName());
            kfApprovalRecord.setRole("物流");
            approvalRecordMapper.insertApprovalRecord(kfApprovalRecord);
        }

        sequence++;
        //  第二审批人：默认周总
        List<ApprovalConfig> approvalConfigList = approvalConfigMapper.selectApprovalConfigList(new ApprovalConfig("DZ_NB_LEADER", "1"));
        if (CollectionUtils.isEmpty(approvalConfigList)) {
            throw new RuntimeException("请检查审批配置信息：DZ_NB_LEADER");
        }
        addApprovalConfig(sequence, approvalConfigList,accountStatement, loginUser);

        sequence++;
        //  第三审批人业务管理员：默认陈雅晴
        List<ApprovalConfig> thirdApprovalConfigList = approvalConfigMapper.selectApprovalConfigList(new ApprovalConfig("DZ_YWGL", "1"));
        if (CollectionUtils.isEmpty(thirdApprovalConfigList)) {
            throw new RuntimeException("请检查审批配置信息：DZ_YWGL");
        }
        addApprovalConfig(sequence, thirdApprovalConfigList,accountStatement, loginUser);

        sequence++;
        //  第四审批人财务经理：张文颖
        List<ApprovalConfig> fourthApprovalConfigList = approvalConfigMapper.selectApprovalConfigList(new ApprovalConfig("DZ_CWJL", "1"));
        if (CollectionUtils.isEmpty(fourthApprovalConfigList)) {
            throw new RuntimeException("请检查审批配置信息：DZ_CWJL");
        }
        addApprovalConfig(sequence, fourthApprovalConfigList,accountStatement, loginUser);

        return kfList.stream().map(SysUser::getUserId).collect(Collectors.toList());
    }

    /**
     * 新增第二，第三审批记录信息
     *
     * @param sequence
     * @param approvalConfigList
     */
    @Transactional(rollbackFor = Exception.class)
    public void addApprovalConfig(int sequence, List<ApprovalConfig> approvalConfigList,AccountStatement accountStatement, LoginUser loginUser) {
        String status = Constants.NOT_APPROVED;
        if (sequence == 2) {
            status = Constants.APPROVE;
        }
        for (ApprovalConfig approvalConfig : approvalConfigList) {
            ApprovalRecord approvalRecord = getApprovalRecord(accountStatement,loginUser);
            approvalRecord.setSequence(sequence);
            approvalRecord.setApprovalStatus(status);
            approvalRecord.setApproverId(approvalConfig.getUserId());
            approvalRecord.setApproverName(approvalConfig.getUsername());
            approvalRecord.setRole(approvalConfig.getUsername());
            approvalRecordMapper.insertApprovalRecord(approvalRecord);
        }
    }

    /**
     * 判断发起人是否是内部人员
     *
     * @param accountStatement
     */
    public boolean isInternalEmployee(AccountStatement accountStatement) {
        //  发起人是内部内部人员
        if (accountStatement == null) {
            throw new RuntimeException("订单信息为空");
        }
        SysUser sysUser = userService.selectUserById(accountStatement.getSponsor());
        if (sysUser == null) {
            throw new RuntimeException("发起人信息错误");
        }
        List<SysRole> roleList = sysUser.getRoles();
        if (CollectionUtils.isEmpty(roleList)) {
            throw new RuntimeException("请配置" + accountStatement.getSponsorName() + "角色信息");
        }
        List<SysRole> roles = roleList.stream().filter(sysRole -> "渠道业务员".equals(sysRole.getRoleName()) || "合伙人".equals(sysRole.getRoleName())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(roles)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 新增对账单
     * @param accountStatement
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public void addAccountStatement(AccountStatement accountStatement) {
        try {
            SysUser sysUser = sysUserService.selectUserByUserName(SecurityUtils.getUsername());
            accountStatement.setCreateBy(sysUser.getUserName());
            accountStatement.setCreateTime(DateUtils.getNowDate());
            accountStatementMapper.insertAccountStatement(accountStatement);
            //项目应扣费用对象
            if(!CollectionUtils.isEmpty(accountStatement.getDeductibleExpensesList())){
                accountStatement.getDeductibleExpensesList().forEach(deductibleExpenses -> {
                    deductibleExpenses.setOrderId(accountStatement.getId());
                    deductibleExpenses.setOrderType("1");
                });
                deductibleExpensesMapper.insertDeductibleExpensess(accountStatement.getDeductibleExpensesList());
            }
            //物流及辅料费用对象
            if(!CollectionUtils.isEmpty(accountStatement.getLogisticsExpensesList())){
                accountStatement.getLogisticsExpensesList().forEach(logisticsExpenses -> {
                    logisticsExpenses.setOrderId(accountStatement.getId());
                    logisticsExpenses.setOrderType("1");
                });
                logisticsExpensesMapper.insertLogisticsExpensess(accountStatement.getLogisticsExpensesList());
            }
            // 维修、配件费用对象
            if(!CollectionUtils.isEmpty(accountStatement.getMaintenanceCostList())){
                accountStatement.getMaintenanceCostList().forEach(maintenanceCost -> {
                    maintenanceCost.setOrderId(accountStatement.getId());
                    maintenanceCost.setOrderType("1");
                });
                maintenanceCostMapper.insertMaintenanceCosts(accountStatement.getMaintenanceCostList());
            }
            //收取客户其他费用
            if(!CollectionUtils.isEmpty(accountStatement.getOtherExpensesList())){
                accountStatement.getOtherExpensesList().forEach(otherExpenses -> {
                    otherExpenses.setOrderId(accountStatement.getId());
                    otherExpenses.setOrderType("1");
                });
                otherExpensesMapper.insertOtherExpensess(accountStatement.getOtherExpensesList());
            }

            //结算机器费用
            if(!CollectionUtils.isEmpty(accountStatement.getStatementExpensesList())){
                accountStatement.getStatementExpensesList().forEach(statementExpenses -> {

                    statementExpenses.setOrderId(accountStatement.getOrderId());
                    statementExpenses.setAccountStatementId(accountStatement.getId());
                    statementExpenses.setOrderType("1");
                    statementExpensesMapper.insertStatementExpenses(statementExpenses);
                });
    //            statementExpensesMapper.insertStatementExpensess(accountStatement.getStatementExpensesList());
            }
            //项目应扣工程费用明细
            if (!CollectionUtils.isEmpty(accountStatement.getProjectEngineerCostList())){
                for (ProjectEngineerCost projectEngineerCost : accountStatement.getProjectEngineerCostList()) {
                    projectEngineerCost.setOrderId(accountStatement.getId());
                    projectEngineerCostMapper.insertProjectEngineerCost(projectEngineerCost);
                }
            }

            //对账单关联订单对象
            if(!CollectionUtils.isEmpty(accountStatement.getStatementOrderList())){
                accountStatement.getStatementOrderList().forEach(statementOrder->{
                    statementOrder.setAccountStatementId(accountStatement.getId());
                    statementOrderMapper.insertStatementOrder(statementOrder);
                });
            }

            //修改订单状态为对账结束
            Order order1 = orderMapper.selectOrderById(accountStatement.getOrderId());
            order1.setOrderStatus(StatusConstants.OrderStatusConstant.orderStatus_5);
            orderMapper.updateOrder(order1);
        } catch (Exception e) {
            throw new RuntimeException("新增对账单失败",e);
        }
    }


    /**
     * 修改对账单
     *
     * @param accountStatement 对账单
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateAccountStatement(AccountStatement accountStatement)
    {
        SysUser sysUser = sysUserService.selectUserByUserName(SecurityUtils.getUsername());
        accountStatement.setUpdateBy(sysUser.getUserName());
        accountStatement.setUpdateTime(DateUtils.getNowDate());
        //删除项目应扣费用对象
        deductibleExpensesMapper.deleteDeductibleExpensesByOrderId(accountStatement.getId());
        if(!CollectionUtils.isEmpty(accountStatement.getDeductibleExpensesList())){
            accountStatement.getDeductibleExpensesList().forEach(deductibleExpenses -> {
                deductibleExpenses.setOrderId(accountStatement.getId());
                deductibleExpenses.setOrderType("1");
            });
            deductibleExpensesMapper.insertDeductibleExpensess(accountStatement.getDeductibleExpensesList());
        }
        //删除物流及辅料费用对象
        logisticsExpensesMapper.deleteLogisticsExpensesByOrderId(accountStatement.getId());
        if(!CollectionUtils.isEmpty(accountStatement.getLogisticsExpensesList())){
            accountStatement.getLogisticsExpensesList().forEach(logisticsExpenses -> {
                logisticsExpenses.setOrderId(accountStatement.getId());
                logisticsExpenses.setOrderType("1");
            });
            logisticsExpensesMapper.insertLogisticsExpensess(accountStatement.getLogisticsExpensesList());
        }
        // 删除维修、配件费用对象
        maintenanceCostMapper.deleteMaintenanceCostByOrderId(accountStatement.getId());
        if(!CollectionUtils.isEmpty(accountStatement.getMaintenanceCostList())){
            accountStatement.getMaintenanceCostList().forEach(maintenanceCost -> {
                maintenanceCost.setOrderId(accountStatement.getId());
                maintenanceCost.setOrderType("1");
            });
            maintenanceCostMapper.insertMaintenanceCosts(accountStatement.getMaintenanceCostList());
        }
        //删除收取客户其他费用
        otherExpensesMapper.deleteOtherExpensesByOrderId(accountStatement.getId());
        if(!CollectionUtils.isEmpty(accountStatement.getOtherExpensesList())){
            accountStatement.getOtherExpensesList().forEach(otherExpenses -> {
                otherExpenses.setOrderId(accountStatement.getId());
                otherExpenses.setOrderType("1");
            });
            otherExpensesMapper.insertOtherExpensess(accountStatement.getOtherExpensesList());
        }

        //结算机器费用
        statementExpensesMapper.deleteStatementExpensesByAccountStatementId(accountStatement.getId());
        if(!CollectionUtils.isEmpty(accountStatement.getStatementExpensesList())){
            accountStatement.getStatementExpensesList().forEach(statementExpenses -> {

                statementExpenses.setOrderId(accountStatement.getOrderId());
                statementExpenses.setAccountStatementId(accountStatement.getId());
                statementExpenses.setOrderType("1");
                statementExpensesMapper.insertStatementExpenses(statementExpenses);
            });
//            statementExpensesMapper.insertStatementExpensess(accountStatement.getStatementExpensesList());
        }

        //对账单关联订单对象
        statementOrderMapper.deleteStatementOrderByStatementId(accountStatement.getId());
        if(!CollectionUtils.isEmpty(accountStatement.getStatementOrderList())){
            accountStatement.getStatementOrderList().forEach(statementOrder->{
                statementOrder.setAccountStatementId(accountStatement.getId());
                statementOrderMapper.insertStatementOrder(statementOrder);
            });
        }
        //项目应扣工程费用明细
        projectEngineerCostMapper.deleteProjectEngineerCostByAccountStatementId(accountStatement.getId());
        if (!CollectionUtils.isEmpty(accountStatement.getProjectEngineerCostList())){
            for (ProjectEngineerCost projectEngineerCost : accountStatement.getProjectEngineerCostList()) {
                projectEngineerCost.setOrderId(accountStatement.getId());
                projectEngineerCostMapper.insertProjectEngineerCost(projectEngineerCost);
            }
        }

        return accountStatementMapper.updateAccountStatement(accountStatement);

    }

    /**
     * 批量删除对账单
     *
     * @param ids 需要删除的对账单主键
     * @return 结果
     */
    @Override
    public int deleteAccountStatementByIds(Long[] ids)
    {
        return accountStatementMapper.deleteAccountStatementByIds(ids);
    }

    /**
     * 删除对账单信息
     *
     * @param id 对账单主键
     * @return 结果
     */
    @Override
    public int deleteAccountStatementById(Long id)
    {
        return accountStatementMapper.deleteAccountStatementById(id);
    }

    @Override
    public List<Map<String,Object>> selectMachineList(AccountStatement accountStatement) {
        //机器明细+使用记录
        List<Map<String,Object>> mlistall= new ArrayList<>();
        List<Map<String,Object>> mlist=outboundOrderMachineMapper.selectMachineListByorderId(accountStatement.getOrderId());
        //  outboundOrderMachineMapper.selectMachineListByorderId(or.getOrderId());
        mlist.forEach(m->{
            Map<String,Object> map = new HashMap<>();
            m.get("product_id").toString();
            m.get("product_name").toString();
            Long productId = Long.valueOf(m.get("product_id").toString());
            //订单未收金额
            MachineRecord machineRecord1 = new MachineRecord();
            machineRecord1.setOrderId(accountStatement.getOrderId());
            List<MachineRecord> machineRecordList = machineRecordMapper.selectMachineRecordList(machineRecord1);
            //取出一台机器的出库和入库记录
            machineRecordList.forEach(machineRecord->{
                if(m.get("machine_no").equals(machineRecord.getMachineNo())) {
                    MachineRecord machineRecord2 = new MachineRecord();
                    machineRecord2.setOrderId(machineRecord.getOrderId());
                    machineRecord2.setMachineId(machineRecord.getMachineId());
                    List<MachineRecord> machineRecordList2 = machineRecordMapper.selectMachineRecordList(machineRecord2);
                    //做了倒序查询，所以两条数据的顺序颠倒了
                    MachineRecord machineRecord3 = machineRecordList2.get(1);
                    MachineRecord machineRecord4 = machineRecordList2.get(0);
                    Date outboundTime = machineRecord3.getOutboundTime();
                    Date warehousingTime = machineRecord4.getWarehousingTime();
                    //此台机器出库总时间
                    differentDays(outboundTime, warehousingTime);
                    String strDifferentDays = String.valueOf(differentDays(outboundTime, warehousingTime));
                    //此台机器日租金
                    OrderProduct orderProduct = new OrderProduct();
                    orderProduct.setOrderId(machineRecord3.getOrderId());
                    orderProduct.setProductId(productId);
                    List<OrderProduct> orderProductList = orderProductMapper.selectOrderProductList(orderProduct);
                    OrderProduct orderProduct1 = orderProductList.get(0);
                    BigDecimal dailyRent = orderProduct1.getDailyRent();
                    //计算单台租金
                    BigDecimal num1 = new BigDecimal(strDifferentDays);
                    BigDecimal rent = dailyRent.multiply(num1);
                    //                Long rent = dailyTotalRent.longValue()*differentDays(outboundTime,warehousingTime);

                    if (machineRecord.getOutboundTime() == null) {
                        Map<String, Object> newmap = new HashMap<>();
                        newmap.put("order_id", accountStatement.getOrderId());
                        newmap.put("outtime", outboundTime);
                        newmap.put("retime", warehousingTime);
                        newmap.put("rent", rent);
                        newmap.put("all_time", differentDays(outboundTime, warehousingTime));
                        newmap.put("model", orderProduct1.getModel());
                        newmap.put("product_id", orderProduct1.getProductId());
                        newmap.put("product_name", orderProduct1.getProductName());
                        newmap.put("machine_id", machineRecord3.getMachineId());
                        newmap.put("machine_no", machineRecord3.getMachineNo());
                        newmap.put("dailyRent", orderProduct1.getDailyRent());
                        mlistall.add(newmap);
                    }
                }
            });
        });

        return mlistall;
    }
    /**
     * 查询费用列表
     *
     * @param accountStatement 对账单
     * @return 对账单
     */
    @Override
    public List<AccountStatement> selectCostList(AccountStatement accountStatement)
    {
        List<AccountStatement> list =  accountStatementMapper.selectAccountStatementList(accountStatement);
        if(!CollectionUtils.isEmpty(list)){
            list.forEach(or->{
                setCostList(or);
            });
        }
        return list;
    }


    /**
     * 设置各个费用明细
     * @param or
     */
    void setCostList(AccountStatement or){
        //项目应扣费用
//        ProjectCostDetails projectCostDetails = new ProjectCostDetails();
//        projectCostDetails.setOrderId(or.getOrderId().toString());
//        List<ProjectCostDetails> projectCostDetailsList = projectCostDetailsMapper.selectProjectCostDetailsList(projectCostDetails);
//        List<DeductibleExpenses> deductibleExpensesList1 = new ArrayList<>();
//        projectCostDetailsList.forEach(details->{
//            DeductibleExpenses deductibleExpenses1 = new DeductibleExpenses();
//            deductibleExpenses1.setExpenseCategory(details.getProjectName());//费用类别中放入项目名称
//            deductibleExpenses1.setOrderId(Long.valueOf(details.getOrderId()));
//            BigDecimal amount = new BigDecimal(details.getProjectCost());
//            deductibleExpenses1.setAmount(amount);
//            deductibleExpensesList1.add(deductibleExpenses1);
//        });

        //物流费用
        LogisticsCost logisticsCost = new LogisticsCost();
        logisticsCost.setOrderId(or.getOrderId());
        List<LogisticsCost> logisticsCostList = logisticsCostMapper.selectLogisticsCostList(logisticsCost);
        List<LogisticsExpenses> LogisticsExpensesList1 = new ArrayList<>();
        logisticsCostList.forEach(logistics->{
            LogisticsExpenses logisticsExpenses1 = new LogisticsExpenses();
            logisticsExpenses1.setExpenseCategory("1");
            logisticsExpenses1.setOrderId(Long.valueOf(logistics.getOrderId()));
            BigDecimal expenses = new BigDecimal(logistics.getLogisticsExpenses());
            logisticsExpenses1.setAmount(expenses);
            LogisticsExpensesList1.add(logisticsExpenses1);
        });

        //维修费用
        MaintenanceCost maintenanceCost = new MaintenanceCost();
        maintenanceCost.setOrderId(or.getOrderId());
        List<MaintenanceCost> maintenanceCostList = maintenanceCostMapper.selectMaintenanceCostList(maintenanceCost);

//        or.setDeductibleExpensesList(deductibleExpensesList1);
        or.setLogisticsExpensesList(LogisticsExpensesList1);
        or.setMaintenanceCostList(maintenanceCostList);
    }

}



//    /**
//     * 查询对账单机器列表
//     *
//     * @param accountStatement 对账单
//     * @return 对账单
//     */
//    @Override
//    public List<MachineRespVo> selectMachineList(AccountStatement accountStatement) {
//        List<AccountStatement> list =  accountStatementMapper.selectAccountStatementList(accountStatement);
//        if(!CollectionUtils.isEmpty(list)){
//            list.forEach(or->{
//                setm(or);
//            });
//        }
//        return list;
//    }
//
//    void setm(AccountStatement or){
//
//        //机器明细+使用记录
//        List<Map<String,Object>> mlistall= new ArrayList<>();
//        List<Map<String,Object>> mlist=outboundOrderMachineMapper.selectMachineListByorderId(or.getOrderId());
//        //  outboundOrderMachineMapper.selectMachineListByorderId(or.getOrderId());
//        mlist.forEach(m->{
//            Map<String,Object> map = new HashMap<>();
//            m.get("product_id").toString();
//            m.get("product_name").toString();
//            Long productId = Long.valueOf(m.get("product_id").toString());
//            //订单未收金额
//            MachineRecord machineRecord1 = new MachineRecord();
//            machineRecord1.setOrderId(or.getOrderId());
//            List<MachineRecord> machineRecordList = machineRecordMapper.selectMachineRecordList(machineRecord1);
//            //取出一台机器的出库和入库记录
//            machineRecordList.forEach(machineRecord->{
//                MachineRecord machineRecord2 = new MachineRecord();
//                machineRecord2.setOrderId(machineRecord.getOrderId());
//                machineRecord2.setMachineId(machineRecord.getMachineId());
//                List<MachineRecord> machineRecordList2 = machineRecordMapper.selectMachineRecordList(machineRecord2);
//                MachineRecord machineRecord3 = machineRecordList2.get(0);
//                MachineRecord machineRecord4 = machineRecordList2.get(1);
//                Date outboundTime =machineRecord3.getOutboundTime();
//                Date warehousingTime = machineRecord4.getWarehousingTime();
//                //此台机器出库总时间
//                differentDays(outboundTime,warehousingTime);
//                String strDifferentDays = String.valueOf(differentDays(outboundTime,warehousingTime));
//                //此台机器日租金
//                OrderProduct orderProduct = new OrderProduct();
//                orderProduct.setOrderId(machineRecord3.getOrderId());
//                orderProduct.setProductId(productId);
//                List<OrderProduct> orderProductList = orderProductMapper.selectOrderProductList(orderProduct);
//                OrderProduct orderProduct1 = orderProductList.get(0);
//                BigDecimal dailyTotalRent = orderProduct1.getDailyTotalRent();
//                //计算单台租金
//                BigDecimal num1 = new BigDecimal(strDifferentDays);
//                BigDecimal rent = dailyTotalRent.multiply(num1);
//                //                Long rent = dailyTotalRent.longValue()*differentDays(outboundTime,warehousingTime);
//
//                if(machineRecord.getOutboundTime()==null){
//                    Map<String,Object> newmap = new HashMap<>();
//                    newmap.put("order_id",or.getOrderId());
//                    newmap.put("outtime",outboundTime);
//                    newmap.put("retime",warehousingTime);
//                    newmap.put("rent",rent);
//                    newmap.put("all_time",differentDays(outboundTime,warehousingTime));
//                    newmap.put("model",orderProduct1.getModel());
//                    newmap.put("product_id",orderProduct1.getProductId());
//                    newmap.put("product_name",orderProduct1.getProductName());
//                    newmap.put("machine_id",machineRecord3.getMachineId());
//                    newmap.put("machine_no",machineRecord3.getMachineNo());
//                    mlistall.add(newmap);
//                }
//            });
//
//
//        });
//
//        or.setMachineList(mlist);
//    }

